feat: add Anthropic support to AI MCP sample - #559
Conversation
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 1efed4c9-8c92-4b6f-9544-ccb65cf3d66b
There was a problem hiding this comment.
Pull request overview
Adds optional Anthropic Claude support to the examples/ai-mcp sample, allowing provider selection via AI_PROVIDER while preserving the existing Teams streaming + MCP tool + citations experience.
Changes:
- Add Anthropic connector/runtime dependencies (and MCP runtime) to the AI MCP sample’s dependency set.
- Select between Azure OpenAI and Anthropic at startup via
AI_PROVIDER, wiring the chosen client into the Agent FrameworkAgent. - Reuse the selected provider for follow-up question generation and manage agent lifecycle during app startup/shutdown.
Reviewed changes
Copilot reviewed 4 out of 5 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
uv.lock |
Locks new dependencies (agent-framework-anthropic, anthropic, mcp, etc.) for the sample. |
examples/ai-mcp/src/main.py |
Reworks follow-up generation to use the selected provider client; wraps app startup in async with agent. |
examples/ai-mcp/src/agent.py |
Adds provider switch (AI_PROVIDER) to instantiate either AnthropicClient or OpenAIChatClient and configure defaults. |
examples/ai-mcp/README.md |
Documents Anthropic option and new environment variables for provider selection. |
examples/ai-mcp/pyproject.toml |
Adds sample dependencies for Anthropic connector and MCP runtime. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| content = response.text or "{}" | ||
| match = re.search(r"\{[\s\S]*\}", content) | ||
| data = cast("dict[str, Any]", json.loads(match.group(0) if match else "{}")) | ||
| follow_ups = data.get("followUps", []) |
| api_key=_require_env("ANTHROPIC_API_KEY"), | ||
| model=_require_env("ANTHROPIC_MODEL"), | ||
| ) | ||
| anthropic_options: AnthropicChatOptions = {"max_tokens": int(getenv("ANTHROPIC_MAX_TOKENS", "4096"))} |
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 1efed4c9-8c92-4b6f-9544-ccb65cf3d66b
Deletion auditI reviewed every removed line against
The complete PR is 147 additions and 72 removals. Ruff, Pyright, lockfile validation, startup, live Claude + MCP, and live follow-up generation pass. |
| ) | ||
| ] | ||
|
|
||
| if isinstance(client, OpenAIChatClient): |
There was a problem hiding this comment.
I think we can potentially collapse this:
response = await client.get_response(
messages,
options={"max_tokens": 200, "response_format": FollowUps},
)
result = response.value
if not isinstance(result, FollowUps):
return []
return [CardAction(type=CardActionType.IM_BACK, title=q, value=q) for q in result.follow_ups]AnthropicChatOptions supports response_format too. agent_framework_anthropic/_chat_client.py maps it to Anthropic's output_format and adds the structured-outputs flag automatically. so Anthropic can get real structured output here instead of regex. Unless this is on purpose?
also, ChatResponse.value already holds the parsed model so no need to RT!
| "agent-framework-core", | ||
| "agent-framework-openai" | ||
| "agent-framework-openai", | ||
| "mcp==1.28.1" |
There was a problem hiding this comment.
are we able to drop this pin on mcp? it looks like we're importing from agent_framework instead, and main resolves mcp
Lily Du (lilyydu)
left a comment
There was a problem hiding this comment.
Cool addition! Left a few comments :)
Summary
AI_PROVIDERValidation
Related PRs